<ClientOnly>
Nuxt 3 提供了一個名為 <ClientOnly>
的元件,用於明確控制為客戶端渲染行為,確保此元件內的元素或內容僅在客戶端呈現,這有助於提升性能並增強使用者體驗。
// app.vue
<template>
<Sidebar />
<ClientOnly>
<Comments />
</ClientOnly>
</template>
<ClientOnly>
:SSR + CSR// components/Sidebar.vue
<template>
<div>
<h1>Sidebar is both SSR and CSR</h1>
</div>
</template>
<script setup lang="ts">
// console.log('<Sidebar>', window)
</script>
<ClientOnly>
內:只有 CSR// components/Comments.vue
<template>
<div>
<h1>Comments is CSR</h1>
</div>
</template>
<script setup lang="ts">
// console.log('<Comments>', window)
</script>
我們分別插入 <Sidebar>
和 <Comments>
,並將 <Comments>
包在 <ClientOnly>
內。
存在 <Sidebar />
的內容 "Sidebar is both SSR and CSR"
。
不存在 <ClientOnly>
的內容 "Comments is CSR"
。
window
物件差異上方 Comments.vue
及 Sidebar.vue
的 console.log(window)
註解打開。
在 Comments.vue
中 console.log(window)
可使用。
在 Sidebar.vue
中 console.log(window)
不可使用,會直接報錯。
因 window
物件僅在瀏覽器中存在,但可透過 Vue 的 Lifecycle Hooks 指定呼叫的時間,如 onMounted()
呼叫 windows
,因此 window
只在客戶端被呼叫。
<template>
<div>
<h1>Sidebar is both SSR and CSR</h1>
</div>
</template>
<script setup lang="ts">
onMounted(()=>{
console.log('<Sidebar>', window)
})
</script>
<ClientOnly>
提供了預設的 slot
,當 <ClientOnly>
元件還沒在客戶端掛載時,如果希望顯示一些預設的內容避免空白頁面可以使用 fallbackTag
+ fallback
或 <template #fallback> ... </template>
來實現:
fallbackTag
+ fallback
// app.vue
<template>
<Sidebar />
<ClientOnly fallbackTag="div" fallback="Loading ...">
<Comments />
</ClientOnly>
</template>
fallbackTag="div"
的作用為 <ClientOnly>
的子組件 <Comments />
尚未在客戶端渲染完成之前,在伺服器端渲染一個 <div>Loading ...</div>
元素作為替代;若沒有指定 fallbackTag
則只會渲染一個空的 <span>
。
<template #fallback> ... </template>
// app.vue
<template>
<Sidebar />
<ClientOnly>
<Comments />
<template #fallback>
<h1>加速等待 ... </h1>
<img src="https://attach.setn.com/newsimages/2019/09/20/2140660-PH.jpg" />
</template>
</ClientOnly>
</template>
加在客戶端渲染前的預設畫面,效果如同方法一;但使用 slot
的方式則可以插入更多且更有彈性的內容。
檢視網頁原始碼比較結果
⚠️如果同時使用 fallbackTag
和 <template #fallback> ... </template>
,只會渲染 <template #fallback> ... </template>
的內容。
如果想使用其他自訂 Components 作為預設畫面,可使用 <template #fallback> <SomeComponent /> </template>
;無法使用 fallbackTag
達成(僅能放入 HTML Tag)。
.client
& .server
除了可以透過上述的 <clientOnly>
來指定特定元素僅在客戶端渲染之外,還可以透過 Components 名稱加上後綴 .client
;而相對的,若是加上後綴 .server
的元件則會僅在伺服器端渲染。
分別建立 components/Sidebar.server.vue
和 components/Comments.client.vue
// app.vue
<template>
<Sidebar />
<Comments />
</template>
接連幾天介紹 Nuxt 3 的各種函式和元件,明天開始會介紹 Nuxt 3 的 Pages 和 Routing,敬請期待!
Components Directory
ClientOnly